#include <dspSimulator/instruction/sploop.h>


bool SPLOOP::checkCondition(std::shared_ptr<DspMachine> dspMachine) {
    return true;
}

void SPLOOP::loadInstIRIntoJit(llvm::LLVMContext *llvmContext, llvm::Module *module,
                               std::shared_ptr<llvm::IRBuilder<>> irBuilder) {

}

std::shared_ptr<Instruction> SPLOOP::decode(std::shared_ptr<InstInfo> instInfo, u64 baseCycle) {
    std::shared_ptr<SPLOOP> sploop;
    auto dspInstInfo = std::dynamic_pointer_cast<DspInstInfo>(instInfo);
    bool isStandardInst = dspInstInfo->isStandardInstruction();
    if (isStandardInst) {
        auto data = vectorToBitSet<32>(dspInstInfo->getBits());
        if (checkBits<21>(data, 2, 0b000001110000000000000) && existStandardCondition(data)) {
            sploop = std::make_shared<SPLOOP>(dspInstInfo->getAddress(), baseCycle);
            sploop->creg_z = extractBits<4>(data, 28);
            sploop->ii = extractBits<5>(data, 23).to_ulong() + 1;
            sploop->s = data[1];
            sploop->p = data[0];
        }
    } else {
        auto data = vectorToBitSet<16>(dspInstInfo->getBits());
        if (data[15] == 0 && checkBits<10>(data, 10, 0b0011) && checkBits<6>(data, 1, 0b110011) && data[0] == 0) {
            sploop = std::make_shared<SPLOOP>(dspInstInfo->getAddress(), baseCycle);
            sploop->isCompactInstruction = true;
            sploop->compactInstKind = "Uspl";
            sploop->ii = extractBits<3>(data, 7).to_ulong();
            sploop->ii += extractBits<1>(data, 14).to_ulong() << 3;
            sploop->ii += 1;
            sploop->PROT = dspInstInfo->getPROT();
            sploop->RS = dspInstInfo->getRS();
            sploop->SAT = dspInstInfo->getSAT();
            sploop->DSZ = dspInstInfo->getDSZ();
            sploop->RS = dspInstInfo->getRS();
            sploop->p = dspInstInfo->getP();
            sploop->fixUpRegOnCompactInstruction();
            sploop->instFormat = InstFormat::Kind1;
        }
    }
    return sploop;
}

void SPLOOP::executeCustom(std::shared_ptr<TargetMachine> targetMachine, ExecutePhase executePhase) {

}

std::shared_ptr<DspInstruction> SPLOOP::clone() {
    return std::make_shared<SPLOOP>(*this);
}

std::string SPLOOP::toString() const {
    std::string res;
    if (!isCompactInstruction) {
        res += getStandardConditionString() + " ";
    }
    res += m_name + " " + std::to_string(ii);
    return res;
}